package com.dingreading.cloud.mall.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.dto.LoginDataDto;
import com.dingreading.cloud.common.util.AccountUtil;
import com.dingreading.cloud.common.util.DateUtil;
import com.dingreading.cloud.common.util.DescribeException;
import com.dingreading.cloud.common.util.EnumType;
import com.dingreading.cloud.common.util.alipay.AliPayApi;
import com.dingreading.cloud.common.util.alipay.AlipayConfig;
import com.dingreading.cloud.common.util.wechat.PayExtraUtil;
import com.dingreading.cloud.common.util.wechat.WxPayBusiness;
import com.dingreading.cloud.mall.entity.OrderForm;
import com.dingreading.cloud.mall.service.OrderFormServiceV5;
import com.dingreading.cloud.mall.util.LoginInfoUtil;
import com.dingreading.cloud.mall.util.OrderFormV3Util;
import com.dingreading.cloud.mall.util.PayDealV3Util;
import com.google.common.collect.Maps;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@RefreshScope
@RestController
@RequestMapping(value = "/front/pay/v3")
@Api(tags = "商城-商品订单支付管理")
public class FrontGoodsPayControllerV3 {

    // 叮叮文化
    @Value("${wx.appId}")
    private String appId;
    @Value("${wx.appSecret}")
    private String appSecret;
    @Value("${wx.mchId}")
    private String mchId;
    @Value("${wx.mchKey}")
    private String mchKey;

    // 叮叮书房文化
    @Value("${wx.sf.appId}")
    private String shAppId;
    @Value("${wx.sf.appSecret}")
    private String shAppSecret;
    @Value("${wx.sf.mchId}")
    private String shMchId;
    @Value("${wx.sf.mchKey}")
    private String shMchKey;

    @Value("${payNotifyUrl}")
    private String notifyUrl;

//    @Resource
//    private OrderFormService orderFormService;
    @Resource
    private OrderFormServiceV5 orderFormService;


    @ApiOperation(value = "商品订单-获取付款二维码")
    @PostMapping(value = "/getGoodsQrCode", produces = "application/json; charset=UTF-8")
    public R<Object> getGoodsQrCode(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "code") @ApiParam(value = "订单号") String code,
            @RequestParam(value = "type") @ApiParam(value = "支付类型 1.微信 2.支付宝") Integer type
    ) {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        // 查询充值订单流水号
        OrderForm form = orderFormService.getByCode(staffUid, code);
        if (null == form)
            return R.fail("获取订单失败");

        // 验证订单有效性
        String msg = OrderFormV3Util.verifyOrderForm(form, true, AccountUtil.isSelfStore(loginDto.getCurrentOperationType()));
        if (StringUtils.isNotBlank(msg)) {
            return R.fail(msg);
        } else {
            // 商品种类包含叮叮书籍，收款公司是叮叮文化，1.叮叮文化 2.叮叮书房
            Integer payCorp = form.getPayCorp();

            if (type.equals(1)) {
                if (StringUtils.isNotBlank(form.getPayChannelCode())) {
                    if (form.getPayChannelCode().startsWith("WXPAY") && !form.getPayChannelCode().equals(EnumType.PayChannelCode.WXPAY_QR.getType())) {
                        return R.fail("已发起" + EnumType.PayChannelCode.getTypeName(form.getPayChannelCode()) + "支付，不能再发起微信扫码支付");
                    }
                }
                orderFormService.updatePayChannelCodeAndCorpPay(staffUid, code, EnumType.PayChannelCode.WXPAY_QR.getType());
                // 微信付款二维码
                Map<String, String> map = Maps.newHashMap();
                map.put("OutTradeNo", form.getCode());
                map.put("body", form.getProjectName());
                map.put("fee", String.valueOf(form.getPayPrice()));
                map.put("tradeType", EnumType.TradeType.WECHAT_NATIVE.getType());
                map.put("attach", PayExtraUtil.getJsonString(EnumType.CodeType.CGSP.getType()));
                // 获取统一下单后的参数
                try {
                    R<Object> payR = new R<>();
                    if (payCorp.equals(1)) {
                        // 叮叮文化
                        payR = WxPayBusiness.Init().unifiedOrderBusiness(request, map, appId, appSecret, mchId, mchKey, notifyUrl);
                    } else {
                        // 叮叮书房
                        payR = WxPayBusiness.Init().unifiedOrderBusiness(request, map, shAppId, shAppSecret, shMchId, shMchKey, notifyUrl);
                    }
                    return payR;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                orderFormService.updatePayChannelCodeAndCorpPay(staffUid, code, EnumType.PayChannelCode.ALIPAY_QR.getType());

                // 支付宝付款二维码
                AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
                model.setOutTradeNo(form.getCode());
                model.setSubject(form.getProjectName());
                model.setTotalAmount(String.valueOf(form.getPayPrice()));
                model.setStoreId(String.valueOf(form.getId()));
                model.setTimeoutExpress("5m");
                model.setBody(PayExtraUtil.getJsonString(EnumType.CodeType.CGSP.getType()));

                String resultStr = "";
                try {
                    if (payCorp.equals(1)) {
                        // 叮叮文化
                        resultStr = AliPayApi.tradePrecreatePay(model, AlipayConfig.getScanNotifyUrl(notifyUrl), AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.ALIPAY_PUBLIC_KEY);
                    } else {
                        // 叮叮书房
                        resultStr = AliPayApi.tradePrecreatePay(model, AlipayConfig.getScanNotifyUrl(notifyUrl), AlipayConfig.SF_APPID, AlipayConfig.SF_RSA_PRIVATE_KEY, AlipayConfig.SF_ALIPAY_PUBLIC_KEY);
                    }
                    JSONObject jsonObject = JSONObject.parseObject(resultStr);
                    JSONObject response = jsonObject.getJSONObject("alipay_trade_precreate_response");
                    Integer responseCode = response.getInteger("code");
                    if (responseCode == 10000) {
                        String qrCode = response.getString("qr_code");
                        if (StringUtils.isNotBlank(qrCode)) {
                            return R.ok(qrCode);
                        } else {
                            return R.fail("获取支付宝付款二维码失败");
                        }
                    } else {
                        String sub_msg = response.getString("sub_msg");
                        return R.fail(sub_msg);
                    }
                } catch (AlipayApiException e) {
                    e.printStackTrace();
                }
            }
        }
        return R.fail("商品订单-获取付款二维码，发起支付异常");
    }


    @ApiOperation(value = "商品订单-微信H5支付")
    @PostMapping(value = "/goodsWxWebPay", produces = "application/json; charset=UTF-8")
    public R<Object> goodsWxWebPay(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "code") @ApiParam(value = "订单号") String code
    ) {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        // 查询充值订单流水号
        OrderForm form = orderFormService.getByCode(staffUid, code);
        if (null == form)
            return R.fail("获取订单失败");

        // 验证订单有效性
        String msg = OrderFormV3Util.verifyOrderForm(form, true, AccountUtil.isSelfStore(loginDto.getCurrentOperationType()));
        if (StringUtils.isNotBlank(msg)) {
            return R.fail(msg);
        } else {
            // 商品种类包含叮叮书籍，收款公司 1.叮叮文化 2.叮叮书房
            Integer payCorp = form.getPayCorp();

            if (StringUtils.isNotBlank(form.getPayChannelCode())) {
                if (form.getPayChannelCode().startsWith("WXPAY") && !form.getPayChannelCode().equals(EnumType.PayChannelCode.WXPAY_H5.getType())) {
                    return R.fail("已发起" + EnumType.PayChannelCode.getTypeName(form.getPayChannelCode()) + "支付，不能再发起微信H5支付");
                }
            }
            orderFormService.updatePayChannelCodeAndCorpPay(staffUid, code, EnumType.PayChannelCode.WXPAY_H5.getType());
            // 微信H5支付
            Map<String, String> map = Maps.newHashMap();
            map.put("OutTradeNo", form.getCode());
            map.put("body", form.getProjectName());
            map.put("fee", String.valueOf(form.getPayPrice()));
            map.put("attach", PayExtraUtil.getJsonString(EnumType.CodeType.CGSP.getType()));
            // 获取统一下单后的参数
            try {
                R<Object> payR = new R<>();
                if (payCorp.equals(1)) {
                    // 叮叮文化
                    payR = WxPayBusiness.Init().h5UnifiedOrder(request, map, appId, mchId, mchKey, notifyUrl);
                } else {
                    // 叮叮书房
                    payR = WxPayBusiness.Init().h5UnifiedOrder(request, map, shAppId, shMchId, shMchKey, notifyUrl);
                }
                return payR;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return R.fail("商品订单-微信H5支付，发起支付异常");
    }


    @ApiOperation(value = "商品订单-支付宝H5支付")
    @GetMapping(value = "/goodsAliWebPay", produces = "text/html; charset=UTF-8")
    public void goodsAliWebPay(
            HttpServletRequest request,
            HttpServletResponse response,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "code") @ApiParam(value = "订单号") String code
    ) throws Exception {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) throw new DescribeException(r.getMsg());
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        // 查询充值订单流水号
        OrderForm form = orderFormService.getByCode(staffUid, code);
        if (null == form)
            throw new DescribeException(500, "获取订单失败");

        // 验证订单有效性
        String msg = OrderFormV3Util.verifyOrderForm(form, true, AccountUtil.isSelfStore(loginDto.getCurrentOperationType()));
        if (StringUtils.isNotBlank(msg)) {
            response.setContentType("application/json; charset=UTF-8");
            response.getWriter().write(JSONObject.toJSONString(r));
            response.getWriter().flush();
            response.getWriter().close();
        } else {
            // 商品种类包含叮叮书籍，收款公司 1.叮叮文化 2.叮叮书房
            Integer payCorp = form.getPayCorp();

            orderFormService.updatePayChannelCodeAndCorpPay(staffUid, code, EnumType.PayChannelCode.ALIPAY_H5.getType());

            // 支付宝H5支付
            AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
            model.setBody(form.getProjectName());
            model.setSubject(form.getProjectName());
            model.setTotalAmount(String.valueOf(form.getPayPrice()));
            model.setOutTradeNo(form.getCode());
            model.setBody(PayExtraUtil.getJsonString(EnumType.CodeType.CGSP.getType()));

            if (payCorp.equals(1)) {
                // 叮叮文化
                AliPayApi.wapPay(
                        response, model, AlipayConfig.getReturnUrl(notifyUrl), AlipayConfig.getNotifyUrl(notifyUrl),
                        AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.ALIPAY_PUBLIC_KEY
                );
            } else {
                // 叮叮书房
                AliPayApi.wapPay(
                        response, model, AlipayConfig.getReturnUrl(notifyUrl), AlipayConfig.getNotifyUrl(notifyUrl),
                        AlipayConfig.SF_APPID, AlipayConfig.SF_RSA_PRIVATE_KEY, AlipayConfig.SF_ALIPAY_PUBLIC_KEY
                );
            }
        }
    }


    @ApiOperation(value = "商品订单-微信公众号支付")
    @PostMapping(value = "/goodsWxJsPay", produces = "application/json; charset=UTF-8")
    public R<Object> goodsWxJsPay(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "code") @ApiParam(value = "订单号") String code,
            @RequestParam(value = "openid") @ApiParam(value = "微信openid") String openid
    ) throws Exception {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        // 查询充值订单流水号
        OrderForm form = orderFormService.getByCode(staffUid, code);
        if (null == form)
            return R.fail("获取订单失败");

        // 验证订单有效性
        String msg = OrderFormV3Util.verifyOrderForm(form, true, AccountUtil.isSelfStore(loginDto.getCurrentOperationType()));
        if (StringUtils.isNotBlank(msg)) {
            return R.fail(msg);
        } else {
            // 商品种类包含叮叮书籍，收款公司 1.叮叮文化 2.叮叮书房
            Integer payCorp = form.getPayCorp();

            if (StringUtils.isNotBlank(form.getPayChannelCode())) {
                if (form.getPayChannelCode().startsWith("WXPAY") && !form.getPayChannelCode().startsWith(EnumType.PayChannelCode.WXPAY_JSAPI.getType())) {
                    return R.fail("已发起" + EnumType.PayChannelCode.getTypeName(form.getPayChannelCode()) + "支付，不能再发起微信公众号支付");
                }
            }
            orderFormService.updatePayChannelCodeAndCorpPay(staffUid, code, EnumType.PayChannelCode.WXPAY_JSAPI.getType());

            // 微信付款二维码
            Map<String, String> map = Maps.newHashMap();
            map.put("openid", openid);
            map.put("OutTradeNo", code);
            map.put("body", form.getProjectName());
            map.put("fee", String.valueOf(form.getPayPrice()));
            map.put("tradeType", EnumType.TradeType.WECHAT_JSAPI.getType());
            map.put("attach", PayExtraUtil.getJsonString(EnumType.CodeType.CGSP.getType()));
            // 获取统一下单后的参数
            try {
                R<Object> payR = new R<>();
                if (payCorp.equals(1)) {
                    // 叮叮文化
                    payR = WxPayBusiness.Init().unifiedOrderBusiness(request, map, appId, appSecret, mchId, mchKey, notifyUrl);
                } else {
                    // 叮叮书房
                    payR = WxPayBusiness.Init().unifiedOrderBusiness(request, map, shAppId, shAppSecret, shMchId, shMchKey, notifyUrl);
                }
                return payR;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return R.fail("商品订单-微信公众号支付，发起支付异常");
    }


    @ApiOperation(value = "商品订单-支付宝电脑网站支付")
    @GetMapping(value = "/goodsAliPagePay", produces = "text/html; charset=UTF-8")
    public void goodsAliPagePay(
            HttpServletRequest request,
            HttpServletResponse response,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "code") @ApiParam(value = "订单号") String code
    ) throws Exception {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) throw new DescribeException(r.getMsg());
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        // 查询充值订单流水号
        OrderForm form = orderFormService.getByCode(staffUid, code);
        if (null == form)
            throw new DescribeException(500, "获取订单失败");
        // 验证订单有效性
        String msg = OrderFormV3Util.verifyOrderForm(form, true, AccountUtil.isSelfStore(loginDto.getCurrentOperationType()));
        if (StringUtils.isNotBlank(msg)) {
            response.setContentType("application/json; charset=UTF-8");
            response.getWriter().write(JSONObject.toJSONString(r));
            response.getWriter().flush();
            response.getWriter().close();
        } else {
            // 商品种类包含叮叮书籍，收款公司 1.叮叮文化 2.叮叮书房
            Integer payCorp = form.getPayCorp();

            orderFormService.updatePayChannelCodeAndCorpPay(staffUid, code, EnumType.PayChannelCode.ALIPAY_PC.getType());

            // 支付宝电脑网站支付
            AlipayTradePagePayModel model = new AlipayTradePagePayModel();
            model.setBody(form.getProjectName());
            model.setSubject(form.getProjectName());
            model.setTotalAmount(String.valueOf(form.getPayPrice()));
            model.setOutTradeNo(form.getCode());
            model.setBody(PayExtraUtil.getJsonString(EnumType.CodeType.CGSP.getType()));

            if (payCorp.equals(1)) {
                // 叮叮文化
                AliPayApi.pagePay(response, model, "", AlipayConfig.getNotifyUrl(notifyUrl), AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.ALIPAY_PUBLIC_KEY);
            } else {
                // 叮叮书房
                AliPayApi.pagePay(response, model, "", AlipayConfig.getNotifyUrl(notifyUrl), AlipayConfig.SF_APPID, AlipayConfig.SF_RSA_PRIVATE_KEY, AlipayConfig.SF_ALIPAY_PUBLIC_KEY);
            }
        }
    }


    @GlobalTransactional
    @ApiOperation(value = "商品订单-金额为0的代金券支付")
    @PostMapping(value = "/couponPay", produces = "application/json; charset=UTF-8")
    public R<Object> couponPay(
            HttpServletRequest request,
            @ApiParam(value = "公司uid") @RequestParam(value = "corpUid") String corpUid,
            @ApiParam(value = "门店uid") @RequestParam(value = "storeUid") String storeUid,
            @ApiParam(value = "门店名称") @RequestParam(value = "storeName") String storeName,
            @ApiParam(value = "员工uid") @RequestParam(value = "staffUid") String staffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "staffName") String staffName,
            @RequestParam(value = "code") @ApiParam(value = "订单号") String code
    ) throws Exception {
        R<Object> r = LoginInfoUtil.getLoginDto(request);
        if (R.isError(r)) return r;
        LoginDataDto loginDto = (LoginDataDto) r.getData();

        // 查询充值订单流水号
        OrderForm form = orderFormService.getByCode(staffUid, code);
        if (null == form)
            return R.fail("获取订单失败");

        // 验证订单有效性
        String msg = OrderFormV3Util.verifyOrderForm(form, false, AccountUtil.isSelfStore(loginDto.getCurrentOperationType()));
        if (StringUtils.isNotBlank(msg)) {
            return R.fail(msg);
        } else {
            if (!code.startsWith(EnumType.CodeCategory.TOB.getType()))
                return R.fail("非toB订单不能支付");

            // 订单支付成功后的处理
            R<Object> payR = PayDealV3Util.payOkGoodsOrder(code, EnumType.PayType.COUPON.getType(), EnumType.TradeType.COUPON.getType(),
                    EnumType.TradeType.COUPON.getName(), "", "", DateUtil.getNowDatetimeStr(),
                    staffUid, staffName, null, 1);
            if (R.isError(payR))
                return payR;
            orderFormService.updatePayChannelCode(staffUid, code, EnumType.PayChannelCode.COUPON.getType());
            return R.ok();
        }
    }

}